
from google.appengine.ext import db
from google.appengine.api import memcache

from Model import Blog, Category, BlogDate, BlogTag

import string
from datetime import datetime
import logging
import random

class BlogDao:
    
    def add(self, title, content, category_name, tags):

        if(title == '' or content == ''):
            return False
        else:
            category = self.getCategoryOfName(category_name)
            tag_list = string.split(tags)
        
            blog = Blog(title=title, content=content)
            if(category):
                blog.category = category
            blog.tag_list = tag_list

            blog.create_date = datetime.today()
            blog.modify_date = datetime.today()
            blog.display = True

            db.put(blog)

            self.rebuildBlogDate()
            self.rebuildBlogTag()

            return True


    def setDisplay(self, key, display = True):

        blog = Blog.get(key)
        if(blog):
            blog.modify_date = datetime.today()
            blog.display = display

            db.put(blog)

            return True
        else:
            return False


    def set(self, key, title, content, category_name, tags):

        if(title == '' or content == ''):
            return False
        else:

            blog = Blog.get(key)
            if(blog):
                blog.title = title
                blog.content = content

                category = self.getCategoryOfName(category_name)
                if(category):
                    blog.category = category

                blog.tag_list = string.split(tags)
                blog.modify_date = datetime.today()

                db.put(blog)

                self.rebuildBlogDate()
                self.rebuildBlogTag()

                return True
            else:
                return False

    def delete(self, key):
        blog = Blog.get(key)
        if(blog):
            db.delete(blog) 
            self.rebuildBlogDate()
            self.rebuildBlogTag()
            return True
        else:
            return False

    def getPrev(self, cur_blog, limit = 1, category_name='', yeardate='', tag=''):
        if cur_blog :
            query = Blog.all()

            if(category_name != ''):
                category = self.getCategoryOfName(category_name)
                if(category):
                    query.filter('category =', category)

            if(yeardate != ''):
                try:
                    yd = datetime.strptime(yeardate, '%Y-%m')

                    yd2month = yd.month + 1
                    yd2year = yd.year
                    if yd2month > 12:
                        yd2month = 1
                        yd2year += 1
                    yd2 = datetime(year=yd2year, month=yd2month, day=yd.day)

                    query.filter('create_date >=', yd)
                    query.filter('create_date <', yd2)
                except ValueError:
                    pass

            if tag != '':
                query.filter('tag_list =', tag)

            query.filter('create_date >', cur_blog.create_date)
            query.order('create_date')
            blogs = query.fetch(limit)
            blogs.reverse()
            return blogs
        else:
            return []


    def getNext(self, cur_blog, limit = 1, category_name=''):
        if cur_blog :
            query = Blog.all()

            if(category_name != ''):
                category = self.getCategoryOfName(category_name)
                if(category):
                    query.filter('category =', category)

            query.filter('create_date <', cur_blog.create_date)
            query.order('-create_date')
            return query.fetch(limit)
        else:
            return []

    def getList(self, upto_datetime=None, category_name = '', yeardate='', show_hide=False, itemPerPage=10, tag=''):

        query = Blog.all()

        if upto_datetime:
            query.filter('create_date <=', upto_datetime)

        if(category_name != ''):
            category = self.getCategoryOfName(category_name)
            if(category):
                query.filter('category =', category)

        if(yeardate != ''):
            try:
                yd = datetime.strptime(yeardate, '%Y-%m')

                yd2month = yd.month + 1
                yd2year = yd.year
                if yd2month > 12:
                    yd2month = 1
                    yd2year += 1
                yd2 = datetime(year=yd2year, month=yd2month, day=yd.day)

                query.filter('create_date >=', yd)
                query.filter('create_date <', yd2)
            except ValueError:
                pass

        if tag != '':
            query.filter('tag_list =', tag)

        if show_hide != True:
            query.filter('display', True)

        query.order('-create_date')

        blogList = query.fetch(itemPerPage + 1)

        return blogList

    def get(self, key):
        return Blog.get(key)         

    def setCategory(self, key, categoryName):
        blog = Blog.get(key)
        if(blog):
            category = self.getCategoryOfName(category_name)
            if(category):
                blog.category = category
                db.put(blog)
                return True
            else:
                return False
        else:
            return False

   






    def getCategoryList(self):
        query = db.GqlQuery("SELECT * FROM Category")
        categoryList = query.fetch(100)
        return categoryList

    def getCategoryOfName(self, name):
        query = db.GqlQuery("SELECT * FROM Category WHERE name = :1", name)
        category = query.get()
        return category

    def addCategory(self, name):
        query = db.GqlQuery("SELECT * FROM Category WHERE name = :1", name)
        category = query.get()
        if category:
            return False
        else:
            category = Category(name=name)
            db.put(category)
            return True
    
    def setCategory(self, key, new_name):
        category = Category.get(key) 
        if category:
            category.name = new_name
            db.put(category)
            return True
        else:
            return False

    def deleteCategory(self, key):
        """
        check no blog under this category, then delete this 
        """
        category = Category.get(key)
        if category :
            query = db.GqlQuery("SELECT * FROM Blog WHERE category = :1", category)
            blogInThisCategory = query.get()
            if blogInThisCategory :
                return False
            else:
                db.delete(category) 
                return True
        else:
            return False

    def getBlogdateList(self, usecache=False):

        cache_key="blog_date.l"

        if usecache:
            cached = memcache.get(key=cache_key)
            if cached is not None:
                return cached


        query = db.GqlQuery("SELECT * FROM BlogDate ORDER BY create_date DESC")
        blogdates = query.fetch(999)
        retval = []
        for blogdate in blogdates:
            retval.append(blogdate.create_date)

        memcache.set(key=cache_key, value=retval, time=3600)

        return retval

    def rebuildBlogDate(self):
       
        dates = []

        """ clear BlogDate """
        query = db.GqlQuery("SELECT __key__ FROM BlogDate")
        blogdates = query.fetch(999)
        db.delete(blogdates)

        """ get all dates """
        query = db.GqlQuery("SELECT * FROM Blog")
        blogs = query.fetch(999)
        for blog in blogs:
            cdate = blog.create_date.date()
            date = datetime(cdate.year, cdate.month, 1)
            if date not in dates:
                dates.append(date)
       
        """ save """
        for date in dates:
            db.put(BlogDate(create_date=date.date()))
       

    def getBlogtagList(self, limit=30, shuffle=True, usecache=False):

        cache_key="blog_tag.l" + str(limit) + "s" + str(shuffle)

        if usecache:
            cached = memcache.get(key=cache_key)
            if cached is not None:
                return cached

        query = db.GqlQuery("SELECT * FROM BlogTag ORDER BY counter DESC")
        blogtags = query.fetch(30)
        retval = []

        ndx = 0
        for blogtag in blogtags:
            
            size = 0
            if ndx < 2:
                size = 1
            elif ndx < 5:
                size = 2
            elif ndx < 10:
                size = 3
            elif ndx < 15:
                size = 4
            else:
                size = 5
            retval.append({'name':blogtag.tag, 'count':blogtag.counter, 'size':size})

            ndx += 1

        if shuffle:
            random.shuffle(retval)

        memcache.set(key=cache_key, value=retval, time=3600)

        return retval

    def rebuildBlogTag(self):
      
        tags = {}

        """ clear BlogTag """
        query = db.GqlQuery("SELECT __key__ FROM BlogTag")
        blogtags = query.fetch(999)
        db.delete(blogtags)

        """ get all tags """
        query = db.GqlQuery("SELECT * FROM Blog")
        blogs = query.fetch(999)
        for blog in blogs:
            tag_list = blog.tag_list
            for tag in tag_list:
                if tag in tags:
                    tags[tag] += 1
                else:
                    tags[tag] = 1
       
        """ save """
        for tag in tags:
            db.put(BlogTag(tag=tag, counter=tags[tag]))
       


